package it.mondogufo.sensorinfo;

import java.util.*;

import android.app.Activity;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;

import android.view.View;
import android.view.LayoutInflater;
import android.view.ViewGroup;

import android.widget.Button;
import android.widget.TextView;
import android.widget.ListView;
import android.widget.LinearLayout;
import android.widget.ArrayAdapter;

import android.content.Context;

import android.hardware.*;

import android.util.Log;

public class SensorInfoActivity extends Activity
{
	private static final int MSG_READSENSOR = 1;
	private static final int SENSOR_DELAY = 3000;
	
	boolean autoRefresh = false;
	ListView listView;
	ArrayList<SensorEventListener> sensorListeners = new ArrayList<SensorEventListener>();
	
	private class SensorInfo {
		
		private String name;
		
		private String vendor;
		
		private String value;
		
		public SensorInfo(String name, String vendor) {
			super();
			this.name = name;
			this.vendor = vendor;
			this.value = "";
		}

		public SensorInfo(Sensor sensor) {
			super();
			this.name = sensor.getName();
			this.vendor = sensor.getVendor();
			this.value = "";
		}
		
		public String getName() {
			return this.name;
		}
		
		public String getVendor() {
			return this.vendor;
		}
		
		public String getValue() {
			return this.value;
		}
		
		public void setValue(String aValue) {
			this.value = aValue;
		}
	}
	
	public class SensorInfoAdapter extends ArrayAdapter<SensorInfo> {

        private int                             resource;
        private LayoutInflater  inflater;

        public SensorInfoAdapter( Context context, int resourceId, List<SensorInfo> objects ) {
                super( context, resourceId, objects );
                resource = resourceId;
                inflater = LayoutInflater.from( context );
        }

        @Override
        public View getView ( int position, View convertView, ViewGroup parent ) {

                // Recuperiamo l'oggetti che dobbiamo inserire a questa posizione
                SensorInfo sensorInfo = getItem( position );

                SensorInfoViewCache viewCache;

                if ( convertView == null ) {
                        convertView = ( LinearLayout ) inflater.inflate( resource, null );
                        viewCache = new SensorInfoViewCache( convertView );
                        convertView.setTag( viewCache );
                }
                else {
                        convertView = ( LinearLayout ) convertView;
                        viewCache = ( SensorInfoViewCache ) convertView.getTag();
                }

                // Prendiamo le view dalla cache e mettiamoci i valori
                TextView tvName = viewCache.getTextViewName();
                tvName.setText( sensorInfo.getName() );

                TextView tvVendor = viewCache.getTextViewVendor();
                tvVendor.setText( sensorInfo.getVendor() );

                TextView tvValue = viewCache.getTextViewValue();
				if (sensorInfo.getValue() != "") {
					tvValue.setText( sensorInfo.getValue() );
				} else {
					tvValue.setText("...");
				}

                return convertView;

        }
	}	
	
	public class SensorInfoViewCache {

        private View            baseView;
        private TextView        textViewName;
        private TextView        textViewVendor;
        private TextView        textViewValue;

        public SensorInfoViewCache ( View baseView ) {
                this.baseView = baseView;
        }

        public TextView getTextViewName () {
                if ( textViewName == null ) {
                        textViewName = ( TextView ) baseView.findViewById( R.id.sensorName );
                }
                return textViewName;
        }

        public TextView getTextViewVendor () {
                if ( textViewVendor == null ) {
                        textViewVendor = ( TextView ) baseView.findViewById( R.id.sensorVendor );
                }
                return textViewVendor;
        }

        public TextView getTextViewValue () {
                if ( textViewValue == null ) {
                        textViewValue = ( TextView ) baseView.findViewById( R.id.sensorValue );
                }
                return textViewValue;
        }

	}

	Handler handler;
		
	public void displaySensorValue()
	{
		ArrayAdapter<SensorInfo> adapter = ( ( ArrayAdapter<SensorInfo> ) listView.getAdapter() );
		adapter.notifyDataSetChanged();
	}
		
	public void displaySensorValueQueue()
	{
		displaySensorValue();
		if (autoRefresh)
			handler.sendEmptyMessageDelayed(MSG_READSENSOR, SENSOR_DELAY);
	}
	
	public void readSensorData(Sensor sensor, float[] values)
	{
		int i;
		ArrayAdapter<SensorInfo> adapter = ( ( ArrayAdapter<SensorInfo> ) listView.getAdapter() );
		String value;
		switch (sensor.getType()) {
			case Sensor.TYPE_ORIENTATION: 
				value = Float.toString(values[0]) + " - " + 
						Float.toString(values[1]) + " - " +
						Float.toString(values[2]);
				break;
			case Sensor.TYPE_ACCELEROMETER: 
				value = Float.toString(values[0]) + " - " + 
						Float.toString(values[1]) + " - " +
						Float.toString(values[2]);
				break;
			case Sensor.TYPE_MAGNETIC_FIELD: 
				value = Float.toString(values[0]);
				break;
			case Sensor.TYPE_LIGHT: 
				value = Float.toString(values[0]);
				break;
			case Sensor.TYPE_PROXIMITY: 
				value = Float.toString(values[0]);
				break;
			default:  value = "unknown";
		}

		for (i = 0 ; i < adapter.getCount() ; i++ ) {
			if (adapter.getItem(i).getName() == sensor.getName()) {
				adapter.getItem(i).setValue(value);
			}
		}
	}
	
	private void displaySensorList()
	{
		int i;
		final SensorManager sensorManager = (SensorManager) this.getSystemService(Context.SENSOR_SERVICE);
		final List<Sensor> sensors = sensorManager.getSensorList(Sensor.TYPE_ALL);
		for (i = 0 ; i < sensors.size() ; i++ )
		{			
			( ( ArrayAdapter<SensorInfo> ) listView.getAdapter() ).add( new SensorInfo(sensors.get(i)) );

		}
		
		handler = new Handler(new Handler.Callback() {
			public boolean handleMessage(Message msg) {
				displaySensorValueQueue();
				return true;
			}
		});
	}
	
	private void attachSensorEvents()
	{
		int i;
		final SensorManager sensorManager = (SensorManager) this.getSystemService(Context.SENSOR_SERVICE);
		final List<Sensor> sensors = sensorManager.getSensorList(Sensor.TYPE_ALL);
		for (i = 0 ; i < sensors.size() ; i++ )
		{
			SensorEventListener listener = new SensorEventListener() {
				public void onAccuracyChanged(Sensor sensor, int accuracy) {
				}
				public void onSensorChanged(SensorEvent event) {
					readSensorData(event.sensor, event.values);
				}
			};
			sensorListeners.add(listener);
			sensorManager.registerListener(listener, sensors.get(i), SensorManager.SENSOR_DELAY_NORMAL);
			
		}
		handler.sendEmptyMessageDelayed(MSG_READSENSOR, SENSOR_DELAY);
		//displaySensorValueQueue();
	}

	private void detachSensorEvents()
	{
		int i;
		final SensorManager sensorManager = (SensorManager) this.getSystemService(Context.SENSOR_SERVICE);
		final List<Sensor> sensors = sensorManager.getSensorList(Sensor.TYPE_ALL);
		for (i = 0 ; i < sensors.size() ; i++ )
		{
			sensorManager.unregisterListener(sensorListeners.get(i));
			
		}
	}
	
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
		
		listView = ( ListView ) findViewById( R.id.sensorListView );
		listView.setAdapter( new SensorInfoAdapter( this, R.layout.sensor, new ArrayList<SensorInfo>() ) );
		displaySensorList();
    }
	

    @Override
    protected void onResume()
	{
		super.onResume();
		autoRefresh = true;
		attachSensorEvents();
	}
	
    @Override
	protected void onPause()
	{
		super.onPause();
		autoRefresh = false;
		detachSensorEvents();
	}

}
